package cn.yto.print.service.impl;

import cn.hutool.json.JSONUtil;
import cn.yto.print.config.CaffeineCacheConfig;
import cn.yto.print.config.PrintFutureContext;
import cn.yto.print.enums.PluginRegistryEnum;
import cn.yto.print.enums.PrintCmdEnum;
import cn.yto.print.model.dto.PrintCacheDTO;
import cn.yto.print.model.request.DeWuPrintRequest;
import cn.yto.print.model.request.PrintTaskRequest;
import cn.yto.print.model.response.DeWuPrintResponse;
import cn.yto.print.model.response.PrintTaskResponse;
import cn.yto.print.plugins.SocketSessionContext;
import cn.yto.print.service.PrintConsumerService;
import cn.yto.print.service.handle.ITextMessageFunction;
import cn.yto.print.service.handle.MessageHandler;
import cn.yto.print.utils.PrintTaskUtil;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

@Slf4j
@Component
public class DeWuMessageHandler extends MessageHandler {

    private SocketSessionContext socketSessionContext;

    @Override
    public void initialize() {
        socketSessionContext = new SocketSessionContext(PluginRegistryEnum.DW, createMessageHandler());
    }

    @Override
    public ITextMessageFunction createMessageHandler() {
        return (session, message) -> {
            CaffeineCacheConfig.getHeartCache().put(PluginRegistryEnum.DW.getCode(), 0);
            DeWuPrintResponse deWuPrintResponse;
            try {
                deWuPrintResponse = JSONUtil.toBean(message.getPayload(), DeWuPrintResponse.class);
            } catch (Exception e) {
                log.error("得物打印组件回执报文解析异常，报文将丢弃~", e);
                return;
            }

            if (StringUtils.isEmpty(deWuPrintResponse.getCmd()) || "getAppInfo".equalsIgnoreCase(deWuPrintResponse.getCmd())) {
                return;
            }
            if (!"print".equals(deWuPrintResponse.getCmd()) || StringUtils.isEmpty(deWuPrintResponse.getRequestID())) {
                return;
            }
            PrintCacheDTO printCache = CaffeineCacheConfig.getPrintCache().getIfPresent(deWuPrintResponse.getRequestID());
            if (null == printCache) {
                log.error("得物打印任务 TaskID：{} 缓存不存在，报文将丢弃~", deWuPrintResponse.getRequestID());
                return;
            }
            CaffeineCacheConfig.getPrintCache().invalidate(deWuPrintResponse.getRequestID());
            PrintTaskResponse printTaskResponse = new PrintTaskResponse();
            printTaskResponse.setCmd(PrintCmdEnum.NOTIFY_PRINT_RESULT.getCmd());
            printTaskResponse.setTaskId(deWuPrintResponse.getRequestID());
            printTaskResponse.setSessionId(printCache.getSessionId());
            printTaskResponse.setTemplateType(printCache.getTemplateType());
            List<PrintTaskResponse.PrintStatus> printStatusList = Lists.newArrayList();
            for (String documentId : printCache.getDocumentIds()) {
                PrintTaskResponse.PrintStatus printStatus = new PrintTaskResponse.PrintStatus();
                printStatus.setStatus(deWuPrintResponse.getStatus());
                printStatus.setDocumentID(documentId);
                printStatus.setMsg(deWuPrintResponse.getMsg());
                printStatusList.add(printStatus);
            }
            printTaskResponse.setPrintStatus(printStatusList);

            CompletableFuture<PrintTaskResponse> future = PrintFutureContext.getResponseFuture(deWuPrintResponse.getRequestID());
            if (null != future) {
                future.complete(printTaskResponse);
            } else {
                PrintConsumerService.handleTimeOutResponse(printTaskResponse);
            }
        };
    }

    @Override
    public DeWuPrintRequest buildPrintRequest(PrintTaskRequest pluginPrintParam) {
        DeWuPrintRequest deWuPrintRequest = new DeWuPrintRequest();
        deWuPrintRequest.setCmd("print");
        deWuPrintRequest.setRequestID(pluginPrintParam.getTaskId());
        deWuPrintRequest.setVersion("1.0");
        DeWuPrintRequest.Task task = new DeWuPrintRequest.Task();
        List<DeWuPrintRequest.Document> documents = new ArrayList<>();
        pluginPrintParam.getDocuments().forEach(doc -> {
            DeWuPrintRequest.Document document = new DeWuPrintRequest.Document();
            document.setPrintData(JSONUtil.toBean(doc.getPrintData(), Map.class));
            document.setCustomContent(doc.getCustomData());
            documents.add(document);
        });
        task.setDocuments(documents);
        task.setTaskID(pluginPrintParam.getTaskId());
        task.setPrinter(pluginPrintParam.getPrinter());
        deWuPrintRequest.setTask(task);
        return deWuPrintRequest;
    }

    @Override
    public CompletableFuture<PrintTaskResponse> processMessage(PrintTaskRequest printParam) {
        DeWuPrintRequest deWuPrintRequest = buildPrintRequest(printParam);
        socketSessionContext.sendPrintRequest(deWuPrintRequest);
        PrintTaskUtil.addPrintTaskCache(printParam);
        CompletableFuture<PrintTaskResponse> completableFuture = new CompletableFuture<>();
        PrintFutureContext.addResponseFuture(printParam.getTaskId(), completableFuture);
        return completableFuture;
    }

    @Override
    public SocketSessionContext getSocketContext() {
        return socketSessionContext;
    }

}
